/**
 * Copyright(c) 2014 Xunton Solutions
 *
 * History:
 *   15-11-27 下午1:38 Created by dwzhang
 */
package com.jade.modules.message.sms.ucpass;

import java.io.Serializable;
import java.util.Date;

import com.jade.framework.base.JadeSystem;
import com.jade.framework.base.util.HttpUtils;
import com.jade.framework.base.util.JsonUtils;
import com.jade.modules.message.sms.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.DateUtils;
import org.apache.http.entity.StringEntity;

/**
 * 采用云之讯平台的发送接口。使用模板方式。
 *
 * @author <a href="mailto:dwzhang@xunton.com">dwzhang</a> 
 * @version 1.0 15-11-27 下午1:38
 */
public class UcpassSmsClient
        extends AbstractSmsClient
{
    protected String accountSid;
    protected String authToken;
    protected String url = "https://api.ucpaas.com";
    protected String defaultTemplateId;
    private String defaultAppId;
    private String version = "2014-06-30";

    public String getAccountSid()
    {
        return accountSid;
    }

    public void setAccountSid(String accountSid)
    {
        this.accountSid = accountSid;
    }

    public String getAuthToken()
    {
        return authToken;
    }

    public void setAuthToken(String authToken)
    {
        this.authToken = authToken;
    }

    public String getUrl()
    {
        return url;
    }

    public void setUrl(String url)
    {
        this.url = url;
    }

    public String getDefaultTemplateId()
    {
        return defaultTemplateId;
    }

    public void setDefaultTemplateId(String defaultTemplateId)
    {
        this.defaultTemplateId = defaultTemplateId;
    }

    public String getDefaultAppId()
    {
        return defaultAppId;
    }

    public void setDefaultAppId(String defaultAppId)
    {
        this.defaultAppId = defaultAppId;
    }

    public String getVersion()
    {
        return version;
    }

    public void setVersion(String version)
    {
        this.version = version;
    }

    public SmsResult send(SmsMessage message, SmsServiceParams params)
    {
        String templateId = params.getString("template_id", defaultTemplateId);
        String appId = params.getString("app_id", defaultAppId);
        String timestamp = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss");
        String u = url + "/" + version + "/Accounts/" + accountSid + "/Messages/templateSMS" + "?sig=" + getSigParamter(
                timestamp);
        TemplateSMS templateSMS = new TemplateSMS();
        templateSMS.setAppId(appId);
        templateSMS.setTemplateId(templateId);
        templateSMS.setTo(StringUtils.join(message.getTo(), ","));
        templateSMS.setParam(params.getString("param"));

        HttpPost httppost = new HttpPost(u);
        httppost.setHeader("Accept", "application/json");
        httppost.setHeader("Content-Type", "application/json;charset=utf-8");
        httppost.setHeader("Authorization", getAuthorization(timestamp));
        String body = "{\"templateSMS\":" + JsonUtils.writeToString(templateSMS) + "}";
        StringEntity entity = new StringEntity(body, "UTF-8");
        entity.setContentType("application/json");
        httppost.setEntity(entity);

        try {
            TemplateSMSResponse response = HttpUtils.doPost(httppost, TemplateSMSResponse.class);
            Response smsResp = response.getResp();
            if (StringUtils.equalsIgnoreCase(smsResp.getRespCode(), "000000")) {
                return new SmsResult(message.getReceiverCount(), smsResp.getTemplateSMS().getSmsId());
            }
            else {
                return new SmsResult(message.getReceiverCount(), SmsStatus.SC_SERVER_ERROR, smsResp.getRespCode());
            }
        }
        catch (Throwable t) {
            JadeSystem.getLog().warn("Can't send sms:" + t.getMessage());
            return new SmsResult(message.getReceiverCount(), SmsStatus.SC_NETWORK_ERROR, t.getMessage());
        }
    }

    protected String getAuthorization(String timestamp)
    {
        String str = accountSid + ":" + timestamp;
        try {
            return Base64.encodeBase64String(str.getBytes("UTF-8"));
        }
        catch (Throwable t) {
            throw new RuntimeException("impossible error");
        }
    }

    protected String getSigParamter(String timestamp)
    {
        String str = accountSid + authToken + timestamp;
        return DigestUtils.md5Hex(str).toUpperCase();
    }

    public static final class TemplateSMS
            implements Serializable
    {
        private String appId;
        private String templateId;
        private String to;
        private String param;

        public String getAppId()
        {
            return appId;
        }

        public void setAppId(String appId)
        {
            this.appId = appId;
        }

        public String getTemplateId()
        {
            return templateId;
        }

        public void setTemplateId(String templateId)
        {
            this.templateId = templateId;
        }

        public String getTo()
        {
            return to;
        }

        public void setTo(String to)
        {
            this.to = to;
        }

        public String getParam()
        {
            return param;
        }

        public void setParam(String param)
        {
            this.param = param;
        }
    }

    public static final class TemplateSMSResponse
            implements Serializable
    {
        Response resp;

        public Response getResp()
        {
            return resp;
        }

        public void setResp(Response resp)
        {
            this.resp = resp;
        }
    }

    public static final class Response
            implements Serializable
    {
        private String respCode;
        private int failure;
        private ResponseSms templateSMS;

        public String getRespCode()
        {
            return respCode;
        }

        public void setRespCode(String respCode)
        {
            this.respCode = respCode;
        }

        public int getFailure()
        {
            return failure;
        }

        public void setFailure(int failure)
        {
            this.failure = failure;
        }

        public ResponseSms getTemplateSMS()
        {
            return templateSMS;
        }

        public void setTemplateSMS(ResponseSms templateSMS)
        {
            this.templateSMS = templateSMS;
        }
    }

    public static final class ResponseSms
            implements Serializable
    {
        private String createDate;
        private String smsId;

        public String getCreateDate()
        {
            return createDate;
        }

        public void setCreateDate(String createDate)
        {
            this.createDate = createDate;
        }

        public String getSmsId()
        {
            return smsId;
        }

        public void setSmsId(String smsId)
        {
            this.smsId = smsId;
        }
    }
}

